home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / machserver / 1.098 / fs / fsTopStream.c < prev    next >
C/C++ Source or Header  |  1990-10-10  |  11KB  |  371 lines

  1. /* 
  2.  * fsStream.c --
  3.  *
  4.  *    The  procedures handle the mapping from streams to
  5.  *    user-level stream IDs,    which are indexes into a per-process array
  6.  *    of stream pointers.
  7.  *
  8.  * Copyright (C) 1987 Regents of the University of California
  9.  * All rights reserved.
  10.  * Permission to use, copy, modify, and distribute this
  11.  * software and its documentation for any purpose and without
  12.  * fee is hereby granted, provided that the above copyright
  13.  * notice appear in all copies.  The University of California
  14.  * makes no representations about the suitability of this
  15.  * software for any purpose.  It is provided "as is" without
  16.  * express or implied warranty.
  17.  */
  18.  
  19. #ifndef lint
  20. static char rcsid[] = "$Header: /sprite/src/kernel/fs/RCS/fsTopStream.c,v 9.1 90/10/08 11:35:29 mendel Exp $ SPRITE (Berkeley)";
  21. #endif not lint
  22.  
  23.  
  24. #include <sprite.h>
  25. #include <fs.h>
  26. #include <fsutil.h>
  27. #include <fsio.h>
  28. #include <fsNameOps.h>
  29. #include <fsconsist.h>
  30. #include <fsStat.h>
  31. #include <proc.h>
  32. #include <sync.h>
  33. #include <rpc.h>
  34.  
  35.  
  36. /*
  37.  * Forward declarations. 
  38.  */
  39. static ReturnStatus GrowStreamList _ARGS_((Fs_ProcessState *fsPtr, 
  40.                     int newLength));
  41.  
  42.  
  43. /*
  44.  *----------------------------------------------------------------------
  45.  *
  46.  * Fs_GetStreamID --
  47.  *
  48.  *    Save the stream pointer in the process's list of stream pointers
  49.  *    and return its index in that list.  The index is used as
  50.  *    a handle for the stream.  E.g. the user supplies the index
  51.  *    in read and write calls and the kernel gets the file pointer
  52.  *    from the list.
  53.  *
  54.  * Results:
  55.  *    SUCCESS        - the operation was successful.
  56.  *    others        - value returned by GrowStreamList.
  57.  *
  58.  * Side effects:
  59.  *    It adds the input streamPtr to the end of the process's list,
  60.  *    if the list is too short (or empty) it is expanded (or created).
  61.  *
  62.  *----------------------------------------------------------------------
  63.  */
  64. ReturnStatus
  65. Fs_GetStreamID(streamPtr, streamIDPtr)
  66.     Fs_Stream    *streamPtr;    /* A reference to an open file */
  67.     int        *streamIDPtr;    /* Return value, the index of the file pointer
  68.                  * in the process's list of open files */
  69. {
  70.     register Fs_ProcessState    *fsPtr;        /* From process's proc table 
  71.                          * entry */
  72.     register Fs_Stream        **streamPtrPtr;    /* Process's list of open 
  73.                          * streams. */
  74.     register int        index;        /* Index into list of open 
  75.                          * streams */
  76.     ReturnStatus        status;        /* Error from growing file 
  77.                          * list. */
  78.  
  79.     fsPtr = (Proc_GetEffectiveProc())->fsPtr;
  80.  
  81.     if (streamPtr == (Fs_Stream *)0) {
  82.     panic( "Zero valued streamPtr");
  83.     }
  84.     if (fsPtr->streamList == (Fs_Stream **)NIL) {
  85.     /*
  86.      * Allocate the initial array of file pointers.
  87.      */
  88.     (void)GrowStreamList(fsPtr, 8);
  89.     }
  90.  
  91.     /*
  92.      * Take the first free streamID, or add a new one to the end.
  93.      */
  94.     for (index = 0, streamPtrPtr = fsPtr->streamList; 
  95.      index < fsPtr->numStreams; 
  96.      index++, streamPtrPtr++) {
  97.     if (*streamPtrPtr == (Fs_Stream *)NIL) {
  98.         *streamPtrPtr = streamPtr;
  99.         *streamIDPtr = index;
  100.         fsPtr->streamFlags[index] = 0;
  101.         return(SUCCESS);
  102.     }
  103.     }
  104.     /*
  105.      * Ran out of room in the original array, allocate a larger
  106.      * array, copy the contents of the original into the beginning,
  107.      * then pick the first empty slot.
  108.      */
  109.     index = fsPtr->numStreams;
  110.     status = GrowStreamList(fsPtr, fsPtr->numStreams * 2);
  111.     if (status == SUCCESS) {
  112.     *streamIDPtr = index;
  113.     fsPtr->streamList[index] = streamPtr;
  114.     fsPtr->streamFlags[index] = 0;
  115.     }
  116.     return(status);
  117. }
  118.  
  119.  
  120. /*
  121.  *----------------------------------------------------------------------
  122.  *
  123.  * Fs_ClearStreamID --
  124.  *
  125.  *    This invalidates a stream ID.  This is called in conjuction
  126.  *    with Fs_Close to close a stream.  The open stream is identified
  127.  *    by the stream ID which this routine invalidates.
  128.  *
  129.  * Results:
  130.  *    None.
  131.  *
  132.  * Side effects:
  133.  *    The stream pointer entry in the open stream list is cleared.
  134.  *
  135.  *----------------------------------------------------------------------
  136.  */
  137. void
  138. Fs_ClearStreamID(streamID, procPtr)
  139.     int streamID;        /* Stream ID to invalidate */
  140.     Proc_ControlBlock *procPtr;    /* (Optional) process pointer */
  141. {
  142.     if (procPtr == (Proc_ControlBlock *)NIL) {
  143.     procPtr = Proc_GetEffectiveProc();
  144.     }
  145.     procPtr->fsPtr->streamList[streamID] = (Fs_Stream *)NIL;
  146. }
  147.  
  148.  
  149. /*
  150.  *----------------------------------------------------------------------
  151.  *
  152.  * GrowStreamList --
  153.  *
  154.  *    Grow a stream ID list.  This routine
  155.  *    allocates another array of file pointers and copies the
  156.  *    values from the original array into the new one.  It also
  157.  *    initializes the new array elements to NIL.  The original
  158.  *    array of pointers is free'd and the pointer to the
  159.  *    array is reset to point to the new array.
  160.  *
  161.  * Results:
  162.  *    SUCCESS        - the operation was successful.
  163.  *    (One could limit the number of streams here, but we don't.)
  164.  *
  165.  * Side effects:
  166.  *    Grows the stream list and the associated array of flag bytes.
  167.  *    The number of streams in the file system state is updated.
  168.  *
  169.  *----------------------------------------------------------------------
  170.  */
  171. static ReturnStatus
  172. GrowStreamList(fsPtr, newLength)
  173.     Fs_ProcessState *fsPtr;    /* The file system state */
  174.     int newLength;        /* The length of the new array */
  175. {
  176.     register int index;
  177.     register Fs_Stream **streamList;
  178.     register char *streamFlags;
  179.  
  180.     streamList = (Fs_Stream **)malloc(newLength * sizeof(Fs_Stream *));
  181.     streamFlags = (char *)malloc(newLength * sizeof(char));
  182.  
  183.     if (fsPtr->numStreams > 0) {
  184.     bcopy((Address)fsPtr->streamList, (Address)streamList, sizeof(Fs_Stream *) * fsPtr->numStreams);
  185.     bcopy((Address)fsPtr->streamFlags, (Address)streamFlags, sizeof(char) * fsPtr->numStreams);
  186.  
  187.     free((Address)fsPtr->streamList);
  188.     free((Address)fsPtr->streamFlags);
  189.     
  190.     for (index=0 ; index < fsPtr->numStreams ; index++) {
  191.         if ((int)streamList[index] != NIL &&
  192.         (unsigned int)streamList[index] < 1024) {
  193.         panic( "GrowStreamList copied bad streamPtr, %x\n",
  194.                        streamList[index]);
  195.         }
  196.     }
  197.     }
  198.  
  199.     fsPtr->streamList = streamList;
  200.     fsPtr->streamFlags =  streamFlags;
  201.  
  202.     for (index=fsPtr->numStreams ; index < newLength ; index++) {
  203.     fsPtr->streamList[index] = (Fs_Stream *)NIL;
  204.     fsPtr->streamFlags[index] = 0;
  205.     }
  206.     fsPtr->numStreams = newLength;
  207.     return(SUCCESS);
  208. }
  209.  
  210.  
  211. /*
  212.  *----------------------------------------------------------------------
  213.  *
  214.  * Fs_GetStreamPtr --
  215.  *
  216.  *    This converts a users stream id into a pointer to the
  217.  *    stream structure for the open stream.  The stream id is
  218.  *    an index into a per-process open stream list.  This does
  219.  *    bounds checking the open stream list and returns the
  220.  *    indexed stream pointer.
  221.  *
  222.  * Results:
  223.  *    SUCCESS        - the operation was successful.
  224.  *    FS_INVALID_ARG    - the stream ID was out of range or the streamPtr
  225.  *              for streamID was NIL.
  226.  *
  227.  * Side effects:
  228.  *    *streamPtrPtr is set to reference the stream structure indexed
  229.  *    by the streamID.
  230.  *
  231.  *----------------------------------------------------------------------
  232.  */
  233. ReturnStatus
  234. Fs_GetStreamPtr(procPtr, streamID, streamPtrPtr)
  235.     Proc_ControlBlock    *procPtr;    /* The owner of an open file list */
  236.     int            streamID;    /* A possible index into the list */
  237.     Fs_Stream        **streamPtrPtr;    /* The pointer from the list*/
  238. {
  239.     if (streamID < 0 || streamID >= procPtr->fsPtr->numStreams) {
  240.     return(FS_INVALID_ARG);
  241.     } else {
  242.     register Fs_Stream *streamPtr;
  243.  
  244.     streamPtr = procPtr->fsPtr->streamList[streamID];
  245.     if (streamPtr == (Fs_Stream *)NIL) {
  246.         return(FS_INVALID_ARG);
  247.     } else if ((unsigned int)streamPtr < 1024) {
  248.         /*
  249.          * There was a time when control stream pointers were not
  250.          * being passed right, or being passed a second time after
  251.          * already being converted to a streamID, which resulted in
  252.          * small integers being kept in the stream list instead of
  253.          * valid stream pointers.  Not sure if that still happens.
  254.          */
  255.         panic( "Stream Ptr # %d was an int %d!\n",
  256.                 streamID, streamPtr);
  257.         return(FS_INVALID_ARG);
  258.     } else {
  259.         *streamPtrPtr = streamPtr;
  260.         return(SUCCESS);
  261.     }
  262.     }
  263. }
  264.  
  265.  
  266. /*
  267.  *----------------------------------------------------------------------
  268.  *
  269.  * Fs_GetNewID --
  270.  *
  271.  *    This gets a new stream ID that refers to the same open file
  272.  *    as the first argument.  After the call the new stream ID will
  273.  *    be equivalent to the old one - system calls that take a stream
  274.  *    ID could be passed either stream ID.  There are two uses of this
  275.  *    routine.  If it doesn't matter what the new stream ID is then
  276.  *    the second argument should point to FS_ANYID.  If the new stream
  277.  *    ID should have a value then the second argument should point
  278.  *    to that value.  If that value was a valid stream ID then the
  279.  *    stream is first closed.
  280.  *
  281.  * Results:
  282.  *    SUCCESS        - the operation was successful.
  283.  *    FS_INVALID_ARG    - newStreamIDPtr was bad or had a bad value.
  284.  *    other        - value returned by FsGrowList.
  285.  *
  286.  * Side effects:
  287.  *    The second argument gets instantiated to a new stream ID.
  288.  *    If the second argument refered to a valid stream ID on entry
  289.  *    (as opposed to pointing to FS_ANYID) then that stream is first closed.
  290.  *
  291.  *----------------------------------------------------------------------
  292.  */
  293. ReturnStatus
  294. Fs_GetNewID(streamID, newStreamIDPtr)
  295.     int streamID;
  296.     int *newStreamIDPtr;
  297. {
  298.     register ReturnStatus     status;
  299.     Fs_Stream             *streamPtr;
  300.     Proc_ControlBlock        *procPtr;
  301.     register Fs_ProcessState    *fsPtr;
  302.  
  303.     if (newStreamIDPtr == (int *)NIL) {
  304.     return(FS_INVALID_ARG);
  305.     }
  306.     procPtr = Proc_GetEffectiveProc();
  307.     status = Fs_GetStreamPtr(procPtr, streamID, &streamPtr);
  308.     if (status != SUCCESS) {
  309.     return(status);
  310.     }
  311.     fsPtr = procPtr->fsPtr;
  312.     if (*newStreamIDPtr == FS_ANYID) {
  313.     Fs_Stream        *newStreamPtr;
  314.  
  315.     Fsio_StreamCopy(streamPtr, &newStreamPtr);
  316.     status = Fs_GetStreamID(newStreamPtr, newStreamIDPtr);
  317.     if (status != SUCCESS) {
  318.         (void)Fs_Close(newStreamPtr);
  319.     }
  320.     return(status);
  321.     } else {
  322.     if (*newStreamIDPtr == streamID) {
  323.         /*
  324.          * Probably a user error.  We just return without fiddling
  325.          * with reference counts.
  326.          */
  327.         return(SUCCESS);
  328.     } else {
  329.         /*
  330.          * Trying to get a specific stream ID.
  331.          */
  332.         register int newStreamID;
  333.  
  334.         newStreamID = *newStreamIDPtr;
  335.         if (newStreamID < 0) {
  336.         return(FS_INVALID_ARG);
  337.         }
  338.         if (newStreamID >= fsPtr->numStreams) {
  339.         register int maxID;
  340.         /*
  341.          * Need to grow the file list to accomodate this stream ID.
  342.          * We do a sanity check on the value of stream ID so
  343.          * we don't nuke ourselves with a huge array.
  344.          */
  345.         maxID = 2 * fsPtr->numStreams;
  346.         maxID = (maxID<128 ? 128 : maxID);
  347.         if (newStreamID > maxID) {
  348.             return(FS_NEW_ID_TOO_BIG);
  349.         }
  350.         status = GrowStreamList(fsPtr, newStreamID + 1 );
  351.         if (status != SUCCESS) {
  352.             return(status);
  353.         }
  354.         } else {
  355.         /*
  356.          * Check to see if *newStreamIDPtr is a valid (Fs_Stream *)
  357.          * and close it if it is.
  358.          */
  359.         register Fs_Stream *oldFilePtr;
  360.  
  361.         oldFilePtr = fsPtr->streamList[newStreamID];
  362.         if (oldFilePtr != (Fs_Stream *)NIL) {
  363.             (void)Fs_Close(oldFilePtr);
  364.         }
  365.         }
  366.         Fsio_StreamCopy(streamPtr, &fsPtr->streamList[newStreamID]);
  367.         return(SUCCESS);
  368.     }
  369.     }
  370. }
  371.